home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / PickOne / sources / PickOne_Support.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  15.8 KB  |  607 lines  |  [TEXT/CWIE]

  1. /*  PickOne_Support.c
  2.                                                                             
  3.     Quickdraw 3D sample code
  4.     
  5.                                                                             
  6.     Nick Thompson
  7.     Scott Kuechle - March 1997
  8.     (c)1994-97 Apple computer Inc., All Rights Reserved                                
  9.  
  10. */
  11.  
  12. /* --------------------------------------------------------------------
  13. ** Includes
  14. */
  15.  
  16. #include    "PickOne_Support.h"
  17. #include    "PickOne_documentStructure.h"
  18.  
  19. #include    "QD3DDrawContext.h"
  20. #include    "QD3DRenderer.h"
  21. #include    "QD3DShader.h"
  22. #include    "QD3DCamera.h"
  23. #include    "QD3DLight.h"
  24. #include    "QD3DGeometry.h"
  25. #include    "QD3DGroup.h"
  26. #include    "QD3DMath.h"
  27. #include    "QD3DTransform.h"
  28.  
  29.  
  30.  
  31. /* --------------------------------------------------------------------
  32. ** Global Variables
  33. */
  34. static     TQ3Point3D    documentGroupCenter;
  35. static    float        documentGroupScale;
  36.  
  37. /* --------------------------------------------------------------------
  38. ** Local Functions
  39. */
  40. TQ3DrawContextObject    MyNewDrawContext(WindowPtr theWindow) ;
  41. TQ3CameraObject         MyNewCamera(WindowPtr theWindow) ;
  42. TQ3GroupObject            MyNewLights(void) ;
  43.  
  44.  
  45. TQ3ViewObject MyNewView(WindowPtr theWindow)
  46. {
  47.     TQ3Status                myStatus;
  48.     TQ3ViewObject            myView;
  49.     TQ3DrawContextObject    myDrawContext;
  50.     TQ3RendererObject        myRenderer;
  51.     TQ3CameraObject            myCamera;
  52.     TQ3GroupObject            myLights;
  53.     
  54.     myView = Q3View_New();
  55.     
  56.     /*     Create and set draw context. */
  57.     if ((myDrawContext = MyNewDrawContext(theWindow)) == nil )
  58.         goto bail;
  59.         
  60.     if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
  61.         goto bail;
  62.  
  63.     Q3Object_Dispose( myDrawContext ) ;
  64.     
  65.     /*     Create and set renderer. */
  66.     
  67.     
  68.     
  69.     /*  this would use the wireframe renderer */
  70.     /*    Not very useful for this app    */
  71. #if 0
  72.     myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  73.     if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  74.         goto bail;
  75.     }
  76. #else
  77.     /*  this would use the interactive plug-in renderer */
  78.  
  79.     if ((myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive)) != nil ) {
  80.         if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  81.             goto bail;
  82.         }
  83.     }
  84.     else {
  85.         goto bail;
  86.     }
  87. #endif
  88.  
  89.     Q3Object_Dispose( myRenderer ) ;
  90.     
  91.     /*     Create and set camera. */
  92.     if ( (myCamera = MyNewCamera(theWindow)) == nil )
  93.         goto bail;
  94.         
  95.     if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
  96.         goto bail;
  97.  
  98.     Q3Object_Dispose( myCamera ) ;
  99.     
  100.     /*     Create and set lights. */
  101.     if ((myLights = MyNewLights()) == nil )
  102.         goto bail;
  103.         
  104.     if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure )
  105.         goto bail;
  106.         
  107.     Q3Object_Dispose(myLights);
  108.  
  109.     /*     Done!!! */
  110.     return ( myView );
  111.     
  112. bail:
  113.     /*     If any of the above failed, then don't return a view. */
  114.     return ( nil );
  115. }
  116.  
  117. /* ---------------------------------------------------------------------------------- */
  118.  
  119. TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow)
  120. {
  121.     TQ3DrawContextData        myDrawContextData;
  122.     TQ3MacDrawContextData    myMacDrawContextData;
  123.     TQ3ColorARGB            ClearColor;
  124.     TQ3DrawContextObject    myDrawContext ;
  125.     
  126.     /*     Set the background color. */
  127.     ClearColor.a = 1.0;
  128.     ClearColor.r = 0.0;
  129.     ClearColor.g = 0.2;
  130.     ClearColor.b = 1.0;
  131.     
  132.     /*     Fill in draw context data. */
  133.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  134.     myDrawContextData.clearImageColor = ClearColor;
  135.     myDrawContextData.paneState = kQ3False;
  136.     myDrawContextData.maskState = kQ3False;
  137.     myDrawContextData.doubleBufferState = kQ3True;
  138.  
  139.     myMacDrawContextData.drawContextData = myDrawContextData;
  140.     
  141.     myMacDrawContextData.window = (CGrafPtr) theWindow;        /*  this is the window associated with the view */
  142.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  143.     myMacDrawContextData.viewPort = nil;
  144.     myMacDrawContextData.grafPort = nil;
  145.     
  146.     /*     Create draw context and return it, if it’s nil the caller must handle */
  147.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  148.  
  149.     return myDrawContext ;
  150. }
  151.  
  152. /* ---------------------------------------------------------------------------------- */
  153.  
  154. TQ3CameraObject MyNewCamera(WindowPtr theWindow)
  155. {
  156.     TQ3ViewAngleAspectCameraData    perspectiveData;
  157.     TQ3CameraData                    someCameraData;
  158.     
  159.     TQ3CameraObject                camera;
  160.     
  161.     TQ3Point3D                     from     = { 0.0, 0.0, 3.0 };
  162.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  163.     TQ3Vector3D                 up         = { 0.0, 1.0, 0.0 };
  164.  
  165.     float                         fieldOfView = 1.0;
  166.     float                         hither         =  0.00001;
  167.     float                         yon         =  10;
  168.     
  169.     TQ3Status                    returnVal = kQ3Failure ;
  170.  
  171.  
  172.     someCameraData.placement.cameraLocation     = from;
  173.     someCameraData.placement.pointOfInterest     = to;
  174.     someCameraData.placement.upVector             = up;
  175.  
  176.     someCameraData.range.hither    = hither;
  177.     someCameraData.range.yon     = yon;
  178.  
  179.     someCameraData.viewPort.origin.x =  -1.0;
  180.     someCameraData.viewPort.origin.y = 1.0;
  181.     someCameraData.viewPort.width = 2.0;
  182.     someCameraData.viewPort.height = 2.0;
  183.     
  184.     perspectiveData.cameraData        = someCameraData;
  185.     perspectiveData.fov                = fieldOfView;
  186.     perspectiveData.aspectRatioXToY    =
  187.         (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  188.         (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  189.         
  190.     camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
  191.  
  192.     return camera ;
  193. }
  194.  
  195.  
  196. /* ---------------------------------------------------------------------------------- */
  197.  
  198. TQ3GroupObject MyNewLights(void)
  199. {
  200.     TQ3GroupPosition        myGroupPosition;
  201.     TQ3GroupObject            myLightList;
  202.     TQ3LightData            myLightData;
  203.     TQ3PointLightData        myPointLightData;
  204.     TQ3DirectionalLightData    myDirectionalLightData;
  205.     TQ3LightObject            myAmbientLight, myPointLight, myFillLight;
  206.     TQ3Point3D                pointLocation = { -10.0, 0.0, 10.0 };
  207.     TQ3Vector3D                fillDirection = { 10.0, 0.0, 10.0 };
  208.     TQ3ColorRGB                WhiteLight = { 1.0, 1.0, 1.0 };
  209.     
  210.     /*     Set up light data for ambient light.  This light data will be used for point and fill */
  211.     /*     light also. */
  212.  
  213.     myLightData.isOn = kQ3True;
  214.     myLightData.color = WhiteLight;
  215.     
  216.     /*     Create ambient light. */
  217.     myLightData.brightness = .3;
  218.     myAmbientLight = Q3AmbientLight_New(&myLightData);
  219.     if ( myAmbientLight == nil )
  220.         goto bail;
  221.     
  222.     /*     Create point light. */
  223.     myLightData.brightness = 0.60;
  224.     myPointLightData.lightData = myLightData;
  225.     myPointLightData.castsShadows = kQ3False;
  226.     myPointLightData.attenuation = kQ3AttenuationTypeNone;
  227.     myPointLightData.location = pointLocation;
  228.     myPointLight = Q3PointLight_New(&myPointLightData);
  229.     if ( myPointLight == nil )
  230.         goto bail;
  231.  
  232.     /*     Create fill light. */
  233.     myLightData.brightness = .2;
  234.     myDirectionalLightData.lightData = myLightData;
  235.     myDirectionalLightData.castsShadows = kQ3False;
  236.     myDirectionalLightData.direction = fillDirection;
  237.     myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
  238.     if ( myFillLight == nil )
  239.         goto bail;
  240.  
  241.     /*     Create light group and add each of the lights into the group. */
  242.     myLightList = Q3LightGroup_New();
  243.     if ( myLightList == nil )
  244.         goto bail;
  245.     myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
  246.     if ( myGroupPosition == 0 )
  247.         goto bail;
  248.     myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
  249.     if ( myGroupPosition == 0 )
  250.         goto bail;
  251.     myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
  252.     if ( myGroupPosition == 0 )
  253.         goto bail;
  254.  
  255.     Q3Object_Dispose( myAmbientLight ) ;
  256.     Q3Object_Dispose( myPointLight ) ;
  257.     Q3Object_Dispose( myFillLight ) ;
  258.  
  259.     /*     Done! */
  260.     return ( myLightList );
  261.     
  262. bail:
  263.     /*     If any of the above failed, then return nothing! */
  264.     return ( nil );
  265. }
  266.  
  267.  
  268. static TQ3GroupPosition MyAddTransformedObjectToGroup( TQ3GroupObject theGroup, TQ3Object theObject, TQ3Vector3D *translation )
  269. {
  270.     TQ3TransformObject    transform;
  271.  
  272.     transform = Q3TranslateTransform_New(translation);
  273.     Q3Group_AddObject(theGroup, transform);    
  274.     Q3Object_Dispose(transform);
  275.     return Q3Group_AddObject(theGroup, theObject);    
  276. }
  277.  
  278.  
  279. TQ3GroupObject MyNewModel()
  280. {
  281.     TQ3GroupObject            myGroup = NULL;
  282.     TQ3GroupObject            mySubGroupCone = NULL,
  283.                             mySubGroupEllipsoid = NULL,
  284.                             mySubGroupBox  = NULL;
  285.     TQ3GeometryObject        myEllipsoid, cone, myBox;
  286.     TQ3ShaderObject            myIlluminationShader ;
  287.     TQ3DisplayGroupState    theState;
  288.     TQ3StyleObject            theStyleObject;
  289.     TQ3SubdivisionStyleData    theSubdivisionStyleData;
  290.  
  291.     
  292.     if ((myGroup = Q3DisplayGroup_New()) != NULL ) {
  293.  
  294.         
  295.         /*  Define a shading type for the group */
  296.         /*  and add the shader to the group */
  297.     
  298.         myIlluminationShader = Q3PhongIllumination_New();
  299. /*        myIlluminationShader = Q3LambertIllumination_New();
  300. */        Q3Group_AddObject(myGroup, myIlluminationShader);
  301.         /*  dispose of the objects we created here */
  302.         if( myIlluminationShader ) 
  303.             Q3Object_Dispose(myIlluminationShader);    
  304.         
  305.         theStyleObject = Q3InterpolationStyle_New(kQ3InterpolationStyleVertex);
  306.         Q3Group_AddObject(myGroup, theStyleObject) ;
  307.         Q3Object_Dispose(theStyleObject);
  308.         
  309.         theSubdivisionStyleData.method = kQ3SubdivisionMethodConstant;
  310.         theSubdivisionStyleData.c1 = 16;
  311.         theSubdivisionStyleData.c2 = 16;
  312.         
  313.         theStyleObject = Q3SubdivisionStyle_New(&theSubdivisionStyleData);
  314.         Q3Group_AddObject(myGroup, theStyleObject) ;
  315.         Q3Object_Dispose(theStyleObject);
  316.  
  317.  
  318.         if ((mySubGroupBox = Q3OrderedDisplayGroup_New()) != NULL ) {
  319.  
  320.             // Define a shading type for the group
  321.             // and add the shader to the group
  322.             myIlluminationShader = Q3PhongIllumination_New();
  323.             Q3Group_AddObject(mySubGroupBox, myIlluminationShader);
  324.             if( myIlluminationShader ) 
  325.                 Q3Object_Dispose(myIlluminationShader);    
  326.  
  327.             myBox = MyNewBox();
  328.             if( myBox ) {
  329.                 Q3Group_AddObject(mySubGroupBox, myBox) ;
  330.                 Q3Object_Dispose( myBox );
  331.             }
  332.  
  333.             myAddMatrixTransformToGroup( mySubGroupBox );
  334.             mySetGroupState(mySubGroupBox);
  335.             Q3Group_AddObject(myGroup, mySubGroupBox) ;
  336.             Q3Object_Dispose(mySubGroupBox);
  337.         }
  338.  
  339.         if ((mySubGroupEllipsoid = Q3OrderedDisplayGroup_New()) != NULL ) {
  340.         
  341.             myEllipsoid = MyNewEllipsoid();
  342.             if( myEllipsoid ) {
  343.                 Q3Group_AddObject(mySubGroupEllipsoid, myEllipsoid);
  344.                 Q3Object_Dispose( myEllipsoid );
  345.             }
  346.  
  347.             myAddMatrixTransformToGroup( mySubGroupEllipsoid );
  348.             mySetGroupState(mySubGroupEllipsoid);
  349.             Q3Group_AddObject(myGroup, mySubGroupEllipsoid) ;
  350.             Q3Object_Dispose(mySubGroupEllipsoid);
  351.         }
  352.  
  353.  
  354.         if ((mySubGroupCone = Q3OrderedDisplayGroup_New()) != NULL ) {
  355.  
  356.             cone = MyNewCone();
  357.             if( cone ) {
  358.                 Q3Group_AddObject(mySubGroupCone, cone);
  359.                 Q3Object_Dispose( cone );
  360.             }
  361.             
  362.             myAddMatrixTransformToGroup( mySubGroupCone );
  363.             mySetGroupState(mySubGroupCone);
  364.             Q3Group_AddObject(myGroup, mySubGroupCone) ;
  365.             Q3Object_Dispose(mySubGroupCone);
  366.             
  367.         }
  368.  
  369.     }    
  370.  
  371.         /*    Now, get the state of the current model    */
  372.         Q3DisplayGroup_GetState(myGroup, &theState);
  373.         
  374.         /*    we don't want to push and pop for PERFORMANCE!!    */
  375.         theState = theState | (kQ3DisplayGroupStateMaskIsInline);
  376.         Q3DisplayGroup_SetState(myGroup,  theState);
  377.         theState = theState | (kQ3DisplayGroupStateMaskIsPicked);
  378.         Q3DisplayGroup_SetState(myGroup,  theState);
  379.  
  380. /*     Done! */
  381.     return ( myGroup );
  382. }
  383.  
  384.  
  385.  
  386. /* ----------------------------------------------------------------------------------------------- */
  387.  
  388. TQ3Status GetDocumentGroupBoundingBox( 
  389.     TQ3ViewObject view,
  390.     TQ3GroupObject    group, 
  391.     TQ3BoundingBox *viewBBox)
  392. {
  393.     TQ3Status        status;
  394.     TQ3ViewStatus    viewStatus ;
  395.     
  396.     status = Q3View_StartBoundingBox( view, kQ3ComputeBoundsExact );
  397.     do {
  398.         status = Q3DisplayGroup_Submit(group, view);
  399.     } while((viewStatus = Q3View_EndBoundingBox( view, viewBBox )) == kQ3ViewStatusRetraverse );
  400.     return status ;
  401. }
  402.  
  403. TQ3Status ComputeCenterOfBoundingBox(TQ3BoundingBox *viewBBox,
  404.                                     TQ3Point3D    *center)
  405. {
  406.  
  407.     if (viewBBox->isEmpty == kQ3True) {
  408.         return kQ3Failure;
  409.     }
  410.     else {
  411.         center->x = (viewBBox->min.x + viewBBox->max.x)/2;
  412.         center->y = (viewBBox->min.y + viewBBox->max.y)/2;
  413.         center->z = (viewBBox->min.z + viewBBox->max.z)/2;
  414.  
  415.         return kQ3Success;
  416.     }
  417. }
  418.  
  419. void MyColorBoxFaces( TQ3BoxData *myBoxData )
  420. {
  421.     TQ3ColorRGB                faceColor ;
  422.     short                     face ;
  423.     
  424.     // sanity check - you need to have set up 
  425.     // the face attribute set for the box data 
  426.     // before calling this.
  427.     
  428.     if( myBoxData->faceAttributeSet == NULL )
  429.         return ;
  430.         
  431.     // make each face of a box a different color
  432.     
  433.     for( face = 0; face < 6; face++) {
  434.         
  435.         myBoxData->faceAttributeSet[face] = Q3AttributeSet_New();
  436.         switch( face ) {
  437.             case 0:
  438.                 faceColor.r = 0.0;
  439.                 faceColor.g = 1.0;
  440.                 faceColor.b = 0.0;
  441.                 break;
  442.             
  443.             case 1:
  444.                 faceColor.r = 0.0;
  445.                 faceColor.g = 1.0;
  446.                 faceColor.b = 0.0;
  447.                 break;
  448.             
  449.             case 2:
  450.                 faceColor.r = 0.0;
  451.                 faceColor.g = 1.0;
  452.                 faceColor.b = 0.0;
  453.                 break;
  454.             
  455.             case 3:
  456.                 faceColor.r = 0.0;
  457.                 faceColor.g = 1.0;
  458.                 faceColor.b = 0.0;
  459.                 break;
  460.             
  461.             case 4:
  462.                 faceColor.r = 0.0;
  463.                 faceColor.g = 1.0;
  464.                 faceColor.b = 0.0;
  465.                 break;
  466.             
  467.             case 5:
  468.                 faceColor.r = 0.0;
  469.                 faceColor.g = 1.0;
  470.                 faceColor.b = 0.0;
  471.                 break;
  472.         }
  473.         Q3AttributeSet_Add(myBoxData->faceAttributeSet[face], kQ3AttributeTypeDiffuseColor, &faceColor);
  474.     }
  475. }
  476.  
  477.  
  478. TQ3GroupObject MyNewBox()
  479. {
  480.     TQ3BoxData                myBoxData;
  481.     TQ3GeometryObject        myBox = NULL;
  482.     TQ3SetObject            faces[6] ;
  483.     short                    face ;
  484.     
  485.         myBoxData.boxAttributeSet = nil;
  486.         myBoxData.faceAttributeSet = faces;
  487.  
  488.         MyColorBoxFaces( &myBoxData ) ;
  489.         
  490.         /*  create the box itself */
  491.  
  492.         Q3Point3D_Set(&myBoxData.origin, 0.5, 0, 0);
  493.         Q3Vector3D_Set(&myBoxData.orientation, 0, 0.5, 0);
  494.         Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 0.5);    
  495.         Q3Vector3D_Set(&myBoxData.minorAxis, 0.5, 0, 0);    
  496.         
  497.         myBox = Q3Box_New(&myBoxData);
  498.  
  499.         for( face = 0; face < 6; face++) {
  500.             if( myBoxData.faceAttributeSet[face] != NULL )
  501.                 Q3Object_Dispose(myBoxData.faceAttributeSet[face]);
  502.         }
  503.         
  504.     return myBox;
  505. }
  506.  
  507.  
  508. TQ3GroupObject MyNewCone()
  509. {
  510.     TQ3ConeData                theConeData;
  511.     TQ3GeometryObject        cone = NULL;
  512.     TQ3ColorRGB                theColor;
  513.     TQ3Status                status;
  514.  
  515.         Q3Point3D_Set(&theConeData.origin, 0, 0, 0);
  516.         Q3Vector3D_Set(&theConeData.orientation, 0, 1.0, 0);
  517.         Q3Vector3D_Set(&theConeData.majorRadius, 0.0, 0.0, 0.26);
  518.         Q3Vector3D_Set(&theConeData.minorRadius, 0.26, 0.0, 0.0);
  519.         theConeData.uMin = 0.0; theConeData.uMax = 1.0;
  520.         theConeData.vMin = 0.0; theConeData.vMax = 1.0;
  521.         theConeData.caps = kQ3EndCapMaskBottom;
  522.         theConeData.interiorAttributeSet = NULL;
  523.         theConeData.bottomAttributeSet = NULL;
  524.         theConeData.faceAttributeSet = NULL;
  525.         theConeData.coneAttributeSet = Q3AttributeSet_New() ;
  526.  
  527.         theColor.r = 1.0; theColor.g = 1.0; theColor.b = 0.0;
  528.  
  529.         status = Q3AttributeSet_Add (theConeData.coneAttributeSet,
  530.                                     kQ3AttributeTypeDiffuseColor,
  531.                                     &theColor);
  532.         
  533.         cone = Q3Cone_New(&theConeData);
  534.  
  535.         Q3Object_Dispose(theConeData.coneAttributeSet);
  536.         
  537.     return cone;
  538. }
  539.  
  540.  
  541. TQ3GroupObject MyNewEllipsoid()
  542. {
  543.     TQ3GeometryObject        myEllipsoid = NULL;
  544.     TQ3EllipsoidData        myEllipsoidData;
  545.     TQ3ColorRGB                theColor;
  546.     TQ3Status                status;
  547.  
  548.         myEllipsoidData.interiorAttributeSet = NULL;
  549.         myEllipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  550.         myEllipsoidData.caps = kQ3EndCapNone;
  551.         
  552.         Q3Point3D_Set(&myEllipsoidData.origin, -1.0, 0.5, 0);
  553.         Q3Vector3D_Set(&myEllipsoidData.orientation, 0, 0.5, 0);
  554.         Q3Vector3D_Set(&myEllipsoidData.minorRadius, 0, 0, -0.4);    
  555.         Q3Vector3D_Set(&myEllipsoidData.majorRadius, 0.5, 0, 0);
  556.         
  557.         myEllipsoidData.uMin = 0.0; myEllipsoidData.uMax = 1.0;
  558.         myEllipsoidData.vMin = 0.0; myEllipsoidData.vMax = 1.0;
  559.  
  560.         theColor.r = 1.0; theColor.g = 0.0; theColor.b = 0.0;
  561.         status = Q3AttributeSet_Add (myEllipsoidData.ellipsoidAttributeSet,
  562.                                     kQ3AttributeTypeDiffuseColor,
  563.                                     &theColor);
  564.  
  565.         myEllipsoid = Q3Ellipsoid_New(&myEllipsoidData);
  566.  
  567.         Q3Object_Dispose(myEllipsoidData.ellipsoidAttributeSet);
  568.  
  569.     return myEllipsoid;
  570. }
  571.  
  572.  
  573. TQ3Status myAddMatrixTransformToGroup( TQ3GroupObject theGroup)
  574. {
  575.     TQ3TransformObject         transform;
  576.     TQ3Matrix4x4            matrix;
  577.     TQ3Status                status;
  578.     TQ3GroupPosition        groupPos;
  579.  
  580.  
  581.         status = kQ3Failure;
  582.         Q3Matrix4x4_SetRotate_XYZ(&matrix, 0.0, 0.0, 0.0);
  583.         transform = Q3MatrixTransform_New(&matrix);
  584.         if (transform != NULL) {
  585.             groupPos = Q3Group_AddObject(theGroup, transform) ;
  586.             if (groupPos != NULL) {
  587.                 status = kQ3Success;
  588.             }
  589.             Q3Object_Dispose(transform);
  590.         }
  591.     
  592.     return status;
  593. }
  594.  
  595. TQ3Status mySetGroupState(TQ3GroupObject theGroup)
  596. {
  597.     TQ3DisplayGroupState    theState;
  598.     TQ3Status                status;
  599.  
  600.         status = Q3DisplayGroup_GetState(theGroup, &theState);
  601.         if (status == kQ3Success) {
  602.             theState = theState | (kQ3DisplayGroupStateMaskIsPicked);
  603.             status = Q3DisplayGroup_SetState(theGroup,  theState);
  604.         }
  605.  
  606.     return status;
  607. }